package com.calvin.study.multithread.threadlocal;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.IntStream;

import com.calvin.study.utils.Print;
import com.calvin.study.utils.ThreadUtil;

import cn.hutool.core.util.RandomUtil;

public class ThreadLocalDemo {

	public static void main(String[] args) {

	}
}

/**
 * @ClassName:ThreadLocalExample01
 * @Description:该示例演示，通过多个线程给线程本地变量赋值后，观察取出的本地变量值，是否被其他线程影响。
 * @date:2023年8月23日 上午10:58:23
 */
class ThreadLocalExample02 {

	private static ThreadLocal<String> threadLocal = new ThreadLocal<String>();

	public static void main(String[] args) {
		//开启10个线程
		IntStream.range(0, 10).forEach(i->new Thread(()-> {
			 String threadName = Thread.currentThread().getName();
			 threadLocal.set(threadName + ":" + i);
	         print(threadName);
		}).start());

	}

	private static void print(String threadName) {
		try {
			// 得到 ThreadLocal 中的值
			String result = threadLocal.get();
			// 打印结果
			System.out.println(threadName + " 取出值：" + result);
		} finally {
			// 移除 ThreadLocal 中的值（防止内存溢出）
			threadLocal.remove();
		}
	}
}

/**
 * 该示例演示，线程本地变量初始化方法。在调用get()方法时，如果重写了初始化方法，则调用初始化方法， 获取返回值 。
 * ※需要注意的是，init初始化方法返回值，必须与声明的ThreadLocal变量返回值相同
 * ※只有在调用get()方法时才会执行init初始化方法，若提前使用set()方法，则不会调用init初始化方法
 */
class ThreadLocalInitDemo {

	private static ThreadLocal<String> threadLocal = new ThreadLocal<String>() {
		@Override
		protected String initialValue() {
			System.out.println(Thread.currentThread().getName()+" 执行threadLocal init 方法");
			return "默认值";
		}
	};

	public static void main(String[] args) {
		new Thread(() -> {
			String threadName = Thread.currentThread().getName();
			//threadLocal.set(threadName + "lIlIlIlI");
			System.out.println(threadName + " 默认值：" + threadLocal.get());
		}, "MyThread-1").start();

		new Thread(() -> {
			String threadName = Thread.currentThread().getName();
			// threadLocal.set(threadName);
			System.out.println(threadName + " 默认值：" + threadLocal.get());
		}, "MyThread-2").start();
	}
}

/**
 * 
 * 该示例演示，线程本地初始化值，效果与上面的demo一致，但这种写法更简洁明了（推荐使用）
 */
class ThreadLocalInitDemo02 {
	private static ThreadLocal<String> threadLocal = ThreadLocal.withInitial(() -> "默认值");

	public static void main(String[] args) {
		new Thread(() -> {
			System.out.println(ThreadUtil.getCurThreadName() + " 值: " + threadLocal.get());
		}, "my-thread-1").start();

		new Thread(() -> {
			System.out.println(ThreadUtil.getCurThreadName() + " 值: " + threadLocal.get());
		}, "my-thread-2").start();
	}
}

class ThreadLocalDateFormat{
	
	private static ThreadLocal<SimpleDateFormat> threadLocal =  ThreadLocal.withInitial(()-> new SimpleDateFormat("mm:ss"));
	
	public static void main(String[] args) {
		ThreadPoolExecutor executor = ThreadUtil.getMixedTargetThreadPool();
		
		for (int i = 1, len = 100; i <= len; i++) {
			int r = i;
			executor.execute(()->{
				String res = threadLocal.get().format(new Date(r * 1000));
				System.out.println(res);
			});
		}
	}
}
